package com.techsen.tsweb.sys.web.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.techsen.tsweb.core.domain.JsonResult;
import com.techsen.tsweb.core.util.JsonUtil;
import com.techsen.tsweb.core.util.SubjectUtil;
import com.techsen.tsweb.core.util.TreeUtil;
import com.techsen.tsweb.core.util.ValidUtil;
import com.techsen.tsweb.core.util.sql.Pager;
import com.techsen.tsweb.sys.domain.Acl;
import com.techsen.tsweb.sys.domain.Menu;
import com.techsen.tsweb.sys.domain.Oper;
import com.techsen.tsweb.sys.domain.Role;
import com.techsen.tsweb.sys.domain.User;
import com.techsen.tsweb.sys.domain.UserRole;
import com.techsen.tsweb.sys.security.ResourceNode;
import com.techsen.tsweb.sys.service.AclService;
import com.techsen.tsweb.sys.service.MenuService;
import com.techsen.tsweb.sys.service.OperService;
import com.techsen.tsweb.sys.service.ResourceService;
import com.techsen.tsweb.sys.service.RoleService;
import com.techsen.tsweb.sys.service.UserRoleService;
import com.techsen.tsweb.sys.service.UserService;
import com.techsen.tsweb.sys.util.SysConst;

@Controller
@RequestMapping("/sys/user")
public class UserController {

    @Resource
    private UserService userService;
    
    @Resource
    private UserRoleService userRoleService;
    
    @Resource
    private RoleService roleService;
    
    @Resource
    private MenuService menuService;
    
    @Resource
    private OperService operService;
    
    @Resource
    private AclService aclService;
    
    @Resource
    private ResourceService resourceService;
    
    /**
     * 进入用户管理界面
     */
    @RequestMapping
    public String index(String menuId, Model model) {
        model.addAttribute("menuId", menuId);
        return "sys/user";
    }
    
    /**
     * 分页查询用户
     */
    @RequestMapping("/pager")
    public @ResponseBody Pager<User> pager(@RequestBody Pager<User> pager) {
        return this.userService.findByPager(pager);
    }
    
    /**
     * 进入添加用户界面
     */
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        return "sys/user-add";
    }
    
    /**
     * 添加用户
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public @ResponseBody JsonResult add(User user) {
        this.userService.add(user);
        return new JsonResult(user);
    }
    
    /**
     * 删除用户
     */
    @RequestMapping("/delete")
    public @ResponseBody JsonResult delete(String id) {
        this.userService.delete(id);
        return new JsonResult(id);
    }
    
    /**
     * 进入修改用户界面
     */
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    public String update(String userId, Model model) {
        User user = this.userService.get(userId);
        model.addAttribute("user", user);
        return "sys/user-update";
    }
    
    /**
     * 修改用户
     */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public @ResponseBody JsonResult update(User user) {
        this.userService.update(user);
        return new JsonResult(user);
    }
    
    /**
     * 进入修改密码界面
     */
    @RequestMapping(value = "/chgpwd", method = RequestMethod.GET)
    public String chgpwd(Model model) {
        return "sys/user-chgpwd";
    }
    
    /**
     * 修改密码
     */
    @RequestMapping(value = "/chgpwd", method = RequestMethod.POST)
    public @ResponseBody JsonResult chgpwd(String oldPwd, String newPwd, String newPwd2) {
        
        System.out.println("-------------");
        System.out.println("oldPwd: " + oldPwd);
        System.out.println("newPwd: " + newPwd);
        System.out.println("newPwd2: " + newPwd2);
        System.out.println("-------------");
        
        User user = (User) SubjectUtil.getSubject().getSession().getAttribute(SysConst.LOGIN_USER);
        user = this.userService.get(user.getId());
        if (!ValidUtil.isValid(oldPwd) || !oldPwd.equals(user.getLoginPwd())) {
            return new JsonResult(oldPwd).setSuccess(false).setMessage("旧密码不正确");
        }
        if (!ValidUtil.isValid(newPwd) || !ValidUtil.isValid(newPwd2) || !newPwd.equals(newPwd2)) {
            return new JsonResult(newPwd).setSuccess(false).setMessage("新密码和确认密码不相同");
        }
        this.userService.update(user.setLoginPwd(newPwd));
        return new JsonResult();
    }
    
    /**
     * 根据登录名查询用户
     */
    @RequestMapping("/users-like-loginAct")
    public @ResponseBody List<User> usersLikeLoginAct(
            @RequestParam(value = "q", required = false) String loginAct) {
        return this.userService.getUsersLikeLoginAct(loginAct);
    }
    
    /*-----------------*/
    
    /**
     * 分配角色
     */
    @RequestMapping(value = "/assignrole", method = RequestMethod.GET)
    public String assignrole(String userId, Model model) {
        if (ValidUtil.isValid(userId)) {
            model.addAttribute("userId", userId);
            
            List<Role> roles = this.roleService.findAll();
            model.addAttribute("roles", roles);
            
            List<String> assignedIds = UserRole.getRoleIdsByUserRoles(this.userRoleService.getListByEntity(new UserRole().setUserId(userId)));
            model.addAttribute("assignedIds", JsonUtil.toJson(assignedIds));
        }
        return "sys/user-assignrole";
    }
    
    /**
     * 分配角色
     */
    @RequestMapping(value = "/assignrole", method = RequestMethod.POST)
    public @ResponseBody JsonResult assignrole(
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "roleIds[]", required = false) List<String> roleIds) {
        List<UserRole> userroles = new ArrayList<UserRole>();
        if (ValidUtil.isValid(roleIds)) {
            for (String roleId : roleIds) {
                UserRole userrole = new UserRole().setUserId(userId).setRoleId(roleId);
                userroles.add(userrole);
            }
        }
        this.userRoleService.deleteByUserId(userId);
        this.userRoleService.batchAdd(userroles);
        return new JsonResult(userroles);
    }
    
    /**
     * 用户授权
     */
    @RequestMapping(value = "/userauth", method = RequestMethod.GET)
    public String userauth(String userId, Model model) {
        if (ValidUtil.isValid(userId)) {
            model.addAttribute("userId", userId);
            
            List<ResourceNode> resources = ResourceNode.convert(this.resourceService.findAll());
            Map<String, List<String>> authedIds = this.resourceService.getResourceIdsByUserId(userId);
            if (ValidUtil.isValid(resources)) {
                if (ValidUtil.isValid(authedIds)) {
                    for (ResourceNode node : resources) {
                        List<String> ids = authedIds.get(node.getResourceType());
                        node.setChecked(ValidUtil.isValid(ids) && ids.contains(node.getId()));
                    }
                }
                model.addAttribute("resources", TreeUtil.toTree(resources));
            }
        }
        return "sys/user-userauth";
    }
    
    /**
     * 用户授权
     */
    @RequestMapping(value = "/userauth", method = RequestMethod.POST)
    public @ResponseBody JsonResult userauth(
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "menuIds[]", required = false) List<String> menuIds,
            @RequestParam(value = "operIds[]", required = false) List<String> operIds) {
        
        List<Acl> acls = new ArrayList<Acl>();
        if (ValidUtil.isValid(menuIds)) {
            List<Menu> menus = this.menuService.getByIds(menuIds);
            Map<String, Integer> aclCodes = new HashMap<String, Integer>();
            for (Menu menu : menus) {
                if (aclCodes.containsKey(menu.getResourceGroup())) {
                    Integer old = aclCodes.get(menu.getResourceGroup());
                    aclCodes.put(menu.getResourceGroup(), old | menu.getAclCode());
                } else {
                    aclCodes.put(menu.getResourceGroup(), menu.getAclCode());
                }
            }
            for (String resourceGroup : aclCodes.keySet()) {
                Integer aclCode = aclCodes.get(resourceGroup);
                Acl acl = new Acl()
                    .setPrincipalType(User.class.getSimpleName().toLowerCase()).setPrincipalId(userId)
                    .setResourceType(Menu.class.getSimpleName().toLowerCase()).setResourceGroup(resourceGroup)
                    .setAclCode(aclCode);
                acls.add(acl);
            }
        }
        if (ValidUtil.isValid(operIds)) {
            List<Oper> opers = this.operService.getByIds(operIds);
            Map<String, Integer> aclCodes = new HashMap<String, Integer>();
            for (Oper oper : opers) {
                if (aclCodes.containsKey(oper.getResourceGroup())) {
                    Integer old = aclCodes.get(oper.getResourceGroup());
                    aclCodes.put(oper.getResourceGroup(), old | oper.getAclCode());
                } else {
                    aclCodes.put(oper.getResourceGroup(), oper.getAclCode());
                }
            }
            for (String resourceGroup : aclCodes.keySet()) {
                Integer aclCode = aclCodes.get(resourceGroup);
                Acl acl = new Acl()
                    .setPrincipalType(User.class.getSimpleName().toLowerCase()).setPrincipalId(userId)
                    .setResourceType(Oper.class.getSimpleName().toLowerCase()).setResourceGroup(resourceGroup)
                    .setAclCode(aclCode);
                acls.add(acl);
            }
        }
        this.aclService.deleteByUserId(userId);
        this.aclService.batchAdd(acls);
        
        return new JsonResult(acls);
    }
    
    /**
     * 查看授权
     */
    @RequestMapping(value = "/viewauth", method = RequestMethod.GET)
    public String viewauth(String userId, Model model) {
        if (ValidUtil.isValid(userId)) {
            model.addAttribute("userId", userId);
            
            List<ResourceNode> resources = ResourceNode.convert(this.resourceService.findAll());
            Map<String, List<String>> authedIds = this.resourceService.getAuthorizedResourceIdsByUserId(userId);
            if (ValidUtil.isValid(resources)) {
                if (ValidUtil.isValid(authedIds)) {
                    for (ResourceNode node : resources) {
                        List<String> ids = authedIds.get(node.getResourceType());
                        node.setChecked(ValidUtil.isValid(ids) && ids.contains(node.getId()));
                    }
                }
                model.addAttribute("resources", TreeUtil.toTree(resources));
            }
        }
        return "sys/user-viewauth";
    }
    
}
